#include "Sdram_W9825g.h"
#include <stdio.h>
#include "fmc.h"

extern SDRAM_HandleTypeDef hsdram1;
//
//void MX_FMC_Init(void)
//{
//  /* USER CODE BEGIN FMC_Init 0 */
//
//  /* USER CODE END FMC_Init 0 */
//
//  FMC_SDRAM_TimingTypeDef SdramTiming = {0};
//
//  /* USER CODE BEGIN FMC_Init 1 */
//
//  /* USER CODE END FMC_Init 1 */
//
//  /** Perform the SDRAM1 memory initialization sequence
//  */
//  hsdram1.Instance = FMC_SDRAM_DEVICE;
//  /* hsdram1.Init */
//  hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
//  hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
//  hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
//  hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
//  hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
//  hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
//  hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
//  hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
//  hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE; 		//使能突发
//  hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1; 	//读通道延时
//  /* SdramTiming */
//  SdramTiming.LoadToActiveDelay = 2;		//加载模式到激活时间的延迟为 2 个时钟周期
//  SdramTiming.ExitSelfRefreshDelay = 8;	//退出自刷新延迟为 8 个时钟周期
//  SdramTiming.SelfRefreshTime = 6;		//自刷新时间为 6 个时钟周期
//  SdramTiming.RowCycleDelay = 6;			//行循环延迟为 6 个时钟周期
//  SdramTiming.WriteRecoveryTime = 2;		//恢复延迟为 2 个时钟周期
//  SdramTiming.RPDelay = 2;				//行预充电延迟为 2 个时钟周期
//  SdramTiming.RCDDelay = 6;				//行到列延迟为 2 个时钟周期
//
//  if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
//  {
//    Error_Handler( );
//  }
//
//  /* USER CODE BEGIN FMC_Init 2 */
//
//  /* USER CODE END FMC_Init 2 */
//}


uint8_t SDRAM_SendCommand(uint32_t CommandMode, uint32_t Bank,
		uint32_t RefreshNum, uint32_t RegVal) {
	uint32_t CommandTarget;
	FMC_SDRAM_CommandTypeDef Command;

	if (Bank == 1)
		CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
	else if (Bank == 2)
		CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;

	Command.CommandMode = CommandMode;
	Command.CommandTarget = CommandTarget;
	Command.AutoRefreshNumber = RefreshNum;
	Command.ModeRegisterDefinition = RegVal;
	if (HAL_SDRAM_SendCommand(&hsdram1, &Command, 0x1000) == HAL_OK)
		return 1;
	else
		return 0;
}

void SDRAM_Init(void) {
	uint32_t temp;

	SDRAM_SendCommand(FMC_SDRAM_CMD_CLK_ENABLE, 1, 1, 0); 		//步骤3：使能时钟信号，SDCKE0 = 1
	HAL_Delay(500);                                        		//步骤4：至少延时200us
	SDRAM_SendCommand(FMC_SDRAM_CMD_PALL, 1, 1, 0);            	//步骤5：发送全部预充电命令
	SDRAM_SendCommand(FMC_SDRAM_CMD_AUTOREFRESH_MODE, 1, 8, 0);	//步骤6：设置自动刷新次数

	temp = SDRAM_MODEREG_BURST_LENGTH_1 |                      	//设置突发长度：1
			SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |               //设置突发类型：连续
			SDRAM_MODEREG_CAS_LATENCY_3 |                       //设置CAS值：3
			SDRAM_MODEREG_OPERATING_MODE_STANDARD |             //设置操作模式：标准
			SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;               //设置突发写模式：单点访问
	SDRAM_SendCommand(FMC_SDRAM_CMD_LOAD_MODE, 1, 1, temp);     //步骤7：装载模式寄存器的值

//SDRAM刷新周期是64ms，行数是8192行，时钟频率是180MHz/2=90MHz
//所有COUNT =  (64ms/8192)/(1/90us)-20 = 64000*90/8192-20 = 683   663.125
// 不分频 180M  (64ms/8192)/(1/180us)-20 = 64000*180/8192-20=1386  1,386.25
	HAL_SDRAM_ProgramRefreshRate(&hsdram1, 683);                //步骤8：设置刷新速率
}

//__no_init uint16_t uhSdramArray[SDRAM_HALF_WORD_SIZE] @SDRAM_BANK1_BASE_ADDRESS; //强制定义数组在SDRAM的内存中
//
//void SDRAM_Test(void) {
//	uint32_t i;
//
//	for (i = 0; i < SDRAM_HALF_WORD_SIZE; i++) {
//		uhSdramArray[i] = i;                                        //对整个数组进行赋值
//	}
//
//	for (i = 0; i < SDRAM_HALF_WORD_SIZE; i += 4096) {
//		printf("uhSdramArray[%d] = %d\r\n", i, uhSdramArray[i]); //对数组中的数据间隔4096个进行串口打印
//	}
//}
